package com.apps.member.account.service.impl;

import ch.qos.logback.core.encoder.EchoEncoder;
import com.apps.member.account.enums.AccountFrozenItemMinType;
import com.apps.member.account.enums.AccountFrozenItemType;
import com.apps.member.account.enums.AccountItemMinType;
import com.apps.member.account.enums.AccountItemType;
import com.apps.member.account.model.po.KupaAccount;
import com.apps.member.account.dao.KupaAccountMapper;
import com.apps.member.account.model.po.KupaAccountFrozenItem;
import com.apps.member.account.model.po.KupaAccountItem;
import com.apps.member.account.service.IKupaAccountFrozenItemService;
import com.apps.member.account.service.IKupaAccountItemService;
import com.apps.member.account.service.IKupaAccountService;
import com.apps.member.account.service.IKupaAccountWithdrawalItemService;
import com.apps.sannotation.constraints.NumMin;
import com.apps.sannotation.keys.JoinKey;
import com.apps.saspect.ThreadLock;
import com.apps.saspect.ValidMethod;
import com.apps.sexctption.DataException;
import com.apps.sexctption.NullException;
import com.apps.sworld.dao.impl.sDaoImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author 大鹏
 * @since 2020-10-02
 */
@Service
public class KupaAccountServiceImpl extends sDaoImpl<KupaAccountMapper, KupaAccount> implements IKupaAccountService
{

    @Autowired
    private IKupaAccountItemService accountItemService;

    @Autowired
    private IKupaAccountFrozenItemService frozenItemService;

    @Autowired
    private IKupaAccountWithdrawalItemService withdrawalItemService;

    @Autowired
    private ApplicationContext applicationContext;

    @ValidMethod
    @ThreadLock
    @Override
    public KupaAccount Income(@JoinKey Integer member_id,
                              @NumMin(min = 0,errMsg = "交易金额必须大于0") BigDecimal price,
                              AccountItemMinType itemMinType)
    {
        KupaAccount account=getOneByMemberId(member_id,new KupaAccount());
        KupaAccountItem accountItem=new KupaAccountItem();
        accountItem.setAccount_id(account.getId());
        accountItem.setMember_id(member_id);
        accountItem.setPrice(price);
        accountItem.setType(AccountItemType.INCOME.name());
        accountItem.setType_min(itemMinType.name());
        accountItem.setBalance(account.getAvailable_balance());
        accountItemService.saveToDB(accountItem);
        try
        {
            account=applicationContext.getBean(this.getClass()).updateAccount(member_id,price,1);
        }catch (Exception e)
        {
            accountItemService.deleteById(accountItem.getId());
        }
        return account;
    }

    @ThreadLock
    @Override
    public KupaAccount Spend(@JoinKey Integer member_id,
                             @NumMin(min = 0,errMsg = "交易金额必须大于0") BigDecimal price,
                             AccountItemMinType itemMinType)
    {
        KupaAccount account=getOneByMemberId(member_id,new KupaAccount());
        KupaAccountItem accountItem=new KupaAccountItem();
        accountItem.setAccount_id(account.getId());
        accountItem.setMember_id(member_id);
        accountItem.setPrice(price);
        accountItem.setType(AccountItemType.SPEND.name());
        accountItem.setType_min(itemMinType.name());
        accountItem.setBalance(account.getAvailable_balance());
        accountItemService.saveToDB(accountItem);
        try
        {
            account=applicationContext.getBean(this.getClass()).updateAccount(member_id,price.multiply(new BigDecimal(-1)),1);
        }catch (Exception e)
        {
            accountItemService.deleteById(accountItem.getId());
        }
        return account;
    }

    @ThreadLock
    @Override
    public KupaAccountFrozenItem Frozen(@JoinKey Integer member_id,
                                        @NumMin(min = 0,errMsg = "交易金额必须大于0") BigDecimal price,
                                        AccountFrozenItemMinType frozenItemMinType)
    {
        //先支出
        KupaAccount account=getOneByMemberId(member_id,new KupaAccount());
        //创建冻结记录
        KupaAccountFrozenItem frozenItem=new KupaAccountFrozenItem();
        frozenItem.setMember_id(member_id);
        frozenItem.setAccount_id(account.getId());
        frozenItem.setPrice(price);
        frozenItem.setType(frozenItemMinType.name());
        frozenItemService.saveToDB(frozenItem);
        try {
            applicationContext.getBean(this.getClass()).updateAccount(member_id, price, 0);
        }catch (Exception e)
        {
            frozenItemService.deleteById(frozenItem.getId());
        }
        return  frozenItem;
    }

    @ThreadLock
    @Override
    public KupaAccount UnFrozen(@JoinKey Integer member_id,
                                Integer frozen_id,
                                AccountFrozenItemMinType frozenItemMinType)
    {
        KupaAccountFrozenItem frozenItem=frozenItemService.getOneById(frozen_id);
        if(null == frozenItem)
            throw new NullException("冻结记录["+frozen_id+"]不存在");
        //删除冻结记录
        frozenItemService.deleteById(frozenItem.getId());
        //更新冻结总额
        return applicationContext.getBean(this.getClass()).updateAccount(member_id,frozenItem.getPrice().multiply(new BigDecimal(-1)),0);
    }

    @ThreadLock
    public KupaAccount updateAccount(@JoinKey Integer member_id,BigDecimal price,int type)
    {
        KupaAccount account = getOneByMemberId(member_id, new KupaAccount());
        if(type == 1)
        {
            if (account.getAvailable_balance().add(price).compareTo(new BigDecimal(0)) <= 0)
                throw new DataException("可用余额不足");
            if (price.compareTo(new BigDecimal(0)) > 0)
                account.setTotal_income(account.getTotal_income().add(price));
            else
                account.setTotal_spend(account.getTotal_spend().add(price.multiply(new BigDecimal(-1))));
        }else if(type == 0)
        {
            if (account.getFrozen_balance().add(price).compareTo(new BigDecimal(0)) <= 0)
                throw new DataException("用户["+member_id+"]冻结数据异常");
            //更新冻结余额
            account.setFrozen_balance(account.getFrozen_balance().add(price));
        }
        //计算可用余额 (总收入-总支出)-冻结余额
        account.setAvailable_balance(account.getTotal_income().subtract(account.getTotal_spend()).subtract(account.getFrozen_balance()));
        return updateById(account);
    }
}
